﻿
export namespace vb {
    export enum CallTag {
        //0x00 Test & Debug
        debug_Test = 0x00,
        debug_Log = 0x01,
        debug_Set_ConsoleLogFunc,
        debug_Set_ConsoleWarnFunc,
        debug_Set_ConsoleErrorFunc,
        //0x10 system
        sys_GetVersionString = 0x10,
        sys_RunApp,
        sys_ExitApp,
        sys_LoadBinaryInApp,
        sys_LoadTextInApp,
        //0x20 app
        app_GetRootPath = 0x20,
        app_LoadBinary,
        app_LoadText,
        app_GetPixelWidth,
        app_GetPixelHeight,
        app_SetGameUpdate,
        app_SetGameRender,
        app_SetClearColor,
        app_SetOnKey,
        app_SetOnPoint,
        //0x30 image
        imageData_SetCtor = 0x30,
        imageData_Create,
        imageData_Decode,
        //0x40 texture
        texture_SetCtor = 0x40,
        texture_Create,
        texture_CreateFromImageData,
        texture_GetWhite,
        texutre_Upload,
        texture_Draw,
        //0x50 sprite
        sprite_SetCtor = 0x50,
        sprite_Create,
        sprite_GetLogo,
        sprite_GetWhite,
        sprite_Draw,
        //0x60 font
        font_SetCtor = 0x60,
        font_Create,
        font_GetSprite,
        font_GetCharWidth,

        //0x100 //sound
        soundsys_SetSoundVol = 0x0100,//系统音量，sound&bgm
        soundsys_SetBGMVol,

        soundsys_PlayBGM,
        soundsys_StopBGM,

        sound_SetCtor,
        sound_Create,
        sound_Play,
        bgm_SetCtor,
        bgm_Create,


    }
    declare function __CallCS(functag: CallTag, ...args: any[]): any;

    export function CallCS(functag: CallTag, ...args: any[]): any {
        return __CallCS(functag, ...args);
    }
    function NewImageData(width: number, height: number, gray: boolean, data: ArrayBuffer | null): ImageData {
        var imgdata = new ImageData(width, height, gray, data);
        return imgdata;
    };
    function NewTexture(handle: number, width: number, height: number, gray: boolean): Texture {
        return new Texture(handle, width, height, gray);
    }
    function NewSprite(index: number, width: number, height: number, gray: boolean
        , pivotX: number, pivotY: number, effect: SpriteEffect): Sprite {
        return new Sprite(index, width, height, gray, pivotX, pivotY, effect);
    }
    function NewFont(index: number, name: string): Font {
        return new Font(index, name);
    }
    function NewSound(index: number): Sound {
        return new Sound(index);
    }
    function NewBGM(index: number): BGM {
        return new BGM(index);
    }
    function _consolelog(message: string): void {
        console.log(message);
    }
    function _consolewarn(message: string): void {
        console.warn(message);
    }
    function _consoleerror(message: string): void {
        console.error(message);
    }
    export function Init() {


        __CallCS(CallTag.imageData_SetCtor, NewImageData);
        __CallCS(CallTag.texture_SetCtor, NewTexture);
        __CallCS(CallTag.sprite_SetCtor, NewSprite);
        __CallCS(CallTag.font_SetCtor, NewFont);
        __CallCS(CallTag.sound_SetCtor, NewSound);
        __CallCS(CallTag.bgm_SetCtor, NewBGM);

        __CallCS(CallTag.debug_Set_ConsoleLogFunc, _consolelog);
        __CallCS(CallTag.debug_Set_ConsoleWarnFunc, _consolewarn);
        __CallCS(CallTag.debug_Set_ConsoleErrorFunc, _consoleerror);

        vb.debug_Log("log", "VoidBox ver=" + vb.sys_GetVersionString());
    }
    ////////////////////////////////////////////////////////////
    //sys_接口, 系统级别
    //得到系统信息
    export function debug_Test(p0: string, p1: string): void {

        return __CallCS(CallTag.debug_Test, p0, p1);
    }

    export function sys_GetVersionString(): string {
        return __CallCS(CallTag.sys_GetVersionString)
    }

    //尝试加载另一个App
    export function sys_RunApp(path: string): void {
        return __CallCS(CallTag.sys_RunApp, path);
    }
    //尝试加载另一个App中的文件
    export function sys_LoadBinaryInApp(path: string, file: string): ArrayBuffer | null {
        return __CallCS(CallTag.sys_LoadBinaryInApp, path, file)
    }
    export function sys_LoadTextInApp(path: string, file: string): string | null {
        return __CallCS(CallTag.sys_LoadTextInApp, path, file);
    }

    ///////////////////////////////////////////////////////////
    //app接口，应用相关操作

    //当前App所在的路径
    export function app_GetRootPath(): string {
        return __CallCS(CallTag.app_GetRootPath)
    }
    export function app_LoadBinary(file: string): ArrayBuffer {
        return __CallCS(CallTag.app_LoadBinary, file)
    }
    export function app_LoadText(file: string): string {
        return __CallCS(CallTag.app_LoadText, file)
    }

    //得到像素尺寸
    export function app_GetPixelWidth(): number {
        return __CallCS(CallTag.app_GetPixelWidth);
    }
    export function app_GetPixelHeight(): number {
        return __CallCS(CallTag.app_GetPixelHeight);
    }



    //设置更新回调
    export function app_SetGameUpdate(updatecallback: (delta: number) => void) {
        __CallCS(CallTag.app_SetGameUpdate, updatecallback);
    }
    export function app_SetGameRender(rendercallback: () => void) {
        __CallCS(CallTag.app_SetGameRender, rendercallback);
    }
    export function app_SetClearColor(color: Color) {
        __CallCS(CallTag.app_SetClearColor, color.r, color.g, color.b, color.a);
    }

    export function app_SetOnKey(keycallback: (keycode: KeyCode, down: boolean) => void) {
        __CallCS(CallTag.app_SetOnKey, keycallback);
    }
    export function app_SetOnPoint(touchcallback: (id: number, down: boolean, x: number, y: number) => void) {
        __CallCS(CallTag.app_SetOnPoint, touchcallback);
    }
    /////////////////////////////////////////////
    //调试接口
    export function debug_Log(type: string, text: string) {
        return __CallCS(CallTag.debug_Log, type, text);
    }

    /////////////////////////////////////////////
    //ImageData 获取接口
    export function imageData_Create(width: number, height: number, gray: boolean): ImageData {
        vb.debug_Log("tag", "imageData_Create call:" + width + "," + height + " gray=" + gray);
        return __CallCS(CallTag.imageData_Create, width, height, gray);
    }
    export function imageData_Decode(data: ArrayBuffer): ImageData {
        return __CallCS(CallTag.imageData_Decode, data);
    }
    //////////////////////////////////////////////////
    //0x40 texture
    export function texture_Create(width: number, height: number, gray: boolean): Texture {
        return __CallCS(CallTag.texture_Create, width, height, gray) as Texture
    }
    export function texture_CreateFromImageData(imagedata: ImageData): Texture {
        return __CallCS(CallTag.texture_CreateFromImageData, imagedata.data, imagedata.width, imagedata.height, imagedata.gray);
    }
    export function texture_GetWhite(): Texture {
        return __CallCS(CallTag.texture_GetWhite);
    }
    export function texutre_Upload(tex: Texture, imagedata: ImageData, x: number, y: number): void {
        return __CallCS(CallTag.texutre_Upload, tex.handle, imagedata.data, x, y, imagedata.width, imagedata.height);
    }
    //sprite
    export function sprite_Create(imagedata: ImageData): Sprite {
        return __CallCS(CallTag.sprite_Create, imagedata.data, imagedata.width, imagedata.height, imagedata.gray);
    }
    export function sprite_GetLogo(): Sprite {
        return __CallCS(CallTag.sprite_GetLogo);
    }
    export function sprite_GetWhite(): Sprite {
        return __CallCS(CallTag.sprite_GetWhite);
    }
    //font
    export function font_Create(buf: ArrayBuffer): Font {
        return __CallCS(CallTag.font_Create, buf);
    }
    export class ImageData {
        constructor(width: number, height: number, gray: boolean, data: ArrayBuffer | null = null) {
            this.width = width;
            this.height = height;
            this.gray = gray;
            if (data == null) {
                this.data = new Uint8Array(this.width * this.height * this.pixelSize);
                vb.debug_Log("log", "imagedata create by null.");
            }
            else {
                this.data = new Uint8Array(data);
                vb.debug_Log("log", "imagedata create by data.");
            }
        }
        readonly width: number;
        readonly height: number;
        readonly gray: boolean;
        readonly data: Uint8Array;
        get pixelSize(): number {
            return this.gray ? 1 : 4;
        }
        GetPixel(x: number, y: number): Color {
            if (this.gray) {
                var c = this.data[y * this.width + this.height] / 255.0;
                return new Color(c, c, c, 1.0);
            }
            else {
                var seek = (y * this.width + this.height) * 4;
                var r = this.data[seek + 0] / 255.0;
                var g = this.data[seek + 1] / 255.0;
                var b = this.data[seek + 2] / 255.0;
                var a = this.data[seek + 3] / 255.0;
                return new Color(r, g, b, a);
            }
        }

    }
    export class Color {
        constructor(r: number = 0, g: number = 0, b: number = 0, a: number = 1) {
            this.r = r;
            this.g = g;
            this.b = b;
            this.a = a;
        }
        r: number;
        g: number;
        b: number;
        a: number;
        static ToNum(c: Color): number {
            var a8 = (c.a * 255) | 0;
            var r8 = (c.r * 255) | 0;
            var g8 = (c.g * 255) | 0;
            var b8 = (c.b * 255) | 0
            if (a8 < 0) a8 = 0;
            if (a8 > 255) a8 = 255;
            if (r8 < 0) r8 = 0;
            if (r8 > 255) r8 = 255;
            if (g8 < 0) g8 = 0;
            if (g8 > 255) g8 = 255;
            if (b8 < 0) b8 = 0;
            if (b8 > 255) b8 = 255;

            return a8 + (r8 << 8) + (g8 << 16) + (b8 << 24)

        }
        static get White(): Color {
            return new Color(1, 1, 1, 1);
        }
    }
    export class Texture {
        constructor(handle: number, width: number, height: number, gray: boolean) {
            this.handle = handle;
            this.width = width;
            this.height = height;
            this.gray = gray;

        }
        readonly handle: number;
        readonly width: number
        readonly height: number;
        readonly gray: boolean;

        private static _drawbuf: Float32Array = new Float32Array(13);
        Draw(x1: number, y1: number, x2: number, y2: number,
            u1: number = 0, v1: number = 0, u2: number = 1, v2: number = 1,
            targetz: number = 0, color: Color = Color.White) {

            Texture._drawbuf[0] = x1;
            Texture._drawbuf[1] = y1;
            Texture._drawbuf[2] = x2;
            Texture._drawbuf[3] = y2;
            Texture._drawbuf[4] = u1;
            Texture._drawbuf[5] = v1;
            Texture._drawbuf[6] = u2;
            Texture._drawbuf[7] = v2;
            Texture._drawbuf[8] = targetz;
            Texture._drawbuf[9] = color.r;
            Texture._drawbuf[10] = color.g;
            Texture._drawbuf[11] = color.b;
            Texture._drawbuf[12] = color.a;
            vb.CallCS(vb.CallTag.texture_Draw, this.handle, Texture._drawbuf.buffer);
        }
    }

    export enum SpriteEffect {
        RGBA = 0,
        Gray = 1,

        //将来扩展 调色板用uniformbuffer 传入
        //PAL8 = 2,暂时去除调色板支持
        //P5A3 只能32色,这种用法必然要引入一个二维PAL图,因为图不多,可以完全用一个RGB化的方法搞,不需要一开始就限制他
        //P5A3 = 3,32color 8alpha
        //P7A1 = 128 color,2alpha

        GrayAsAlpha = 4,//for Font
    }
    export class Sprite {
        constructor(index: number, width: number, height: number, gray: boolean, pivotX: number, pivotY: number, effect: SpriteEffect) {
            this.index = index;
            this.width = width;
            this.height = height;
            this.pivotX = pivotX;
            this.pivotY = pivotY;
            this.gray = gray;
            this.effect = effect;
        }
        readonly index: number;
        readonly width: number;
        readonly height: number;
        readonly gray: boolean;

        readonly pivotX: number;
        readonly pivotY: number;
        readonly effect: SpriteEffect;

        private static _drawbuf: Float32Array = new Float32Array(13);
        Draw(x: number, y: number, z: number, rotate: number, scaleX: number, scaleY: number, color: Color): void {

            Sprite._drawbuf[0] = x;
            Sprite._drawbuf[1] = y;
            Sprite._drawbuf[2] = z;
            Sprite._drawbuf[3] = rotate;
            Sprite._drawbuf[4] = scaleX;
            Sprite._drawbuf[5] = scaleY;
            Sprite._drawbuf[6] = color.r;
            Sprite._drawbuf[7] = color.g;
            Sprite._drawbuf[8] = color.b;
            Sprite._drawbuf[9] = color.a;
            vb.CallCS(vb.CallTag.sprite_Draw, this.index, Sprite._drawbuf.buffer);
        }
    }

    export class Font {
        constructor(index: number, name: string) {
            this.index = index;
            this.name = name;
        }
        private index: number;
        readonly name: string;

        GetSprite(fontsize: number, charcode: number): Sprite {
            return vb.CallCS(vb.CallTag.font_GetSprite, this.index, fontsize, charcode);
        }
        GetCharWidth(fontsize: number, charcode: number): number {
            return vb.CallCS(vb.CallTag.font_GetCharWidth, this.index, fontsize, charcode);
        }
    }
    export class Sound {
        constructor(index: number) {
            this.index = index;
        }
        index: number;

        Play(vol: number = 1.0): void {
            vb.CallCS(vb.CallTag.sound_Play, this.index, vol);
        }
    }
    export class BGM {
        constructor(index: number) {
            this.index = index;
        }
        index: number;
    }

    export class SoundSystem {
        static SetSoundVol(value: number): void {
            vb.CallCS(vb.CallTag.soundsys_SetSoundVol, value);
        }
        static SetBGMVol(value: number): void {
            vb.CallCS(vb.CallTag.soundsys_SetBGMVol, value);
        }
        static PlayBGM(bgm: BGM, vol: number = 1.0): void {
            vb.CallCS(vb.CallTag.soundsys_PlayBGM, bgm.index, vol);
        }
        static StopBGM(): void {
            vb.CallCS(vb.CallTag.soundsys_StopBGM);
        }

        static CreateSound(data: ArrayBuffer): Sound {
            return vb.CallCS(vb.CallTag.sound_Create, data);
        }
        static CreateBGM(data: ArrayBuffer): BGM {
            return vb.CallCS(vb.CallTag.bgm_Create, data);
        }
    }

    export enum KeyCode {
        //
        // 摘要:
        //     An unknown key.
        Unknown = -1,
        //
        // 摘要:
        //     The spacebar key.
        Space = 0x20,
        //
        // 摘要:
        //     The apostrophe key.
        Apostrophe = 39,
        //
        // 摘要:
        //     The comma key.
        Comma = 44,
        //
        // 摘要:
        //     The minus key.
        Minus = 45,
        //
        // 摘要:
        //     The period key.
        Period = 46,
        //
        // 摘要:
        //     The slash key.
        Slash = 47,
        //
        // 摘要:
        //     The 0 key.
        D0 = 48,
        //
        // 摘要:
        //     The 1 key.
        D1 = 49,
        //
        // 摘要:
        //     The 2 key.
        D2 = 50,
        //
        // 摘要:
        //     The 3 key.
        D3 = 51,
        //
        // 摘要:
        //     The 4 key.
        D4 = 52,
        //
        // 摘要:
        //     The 5 key.
        D5 = 53,
        //
        // 摘要:
        //     The 6 key.
        D6 = 54,
        //
        // 摘要:
        //     The 7 key.
        D7 = 55,
        //
        // 摘要:
        //     The 8 key.
        D8 = 56,
        //
        // 摘要:
        //     The 9 key.
        D9 = 57,
        //
        // 摘要:
        //     The semicolon key.
        Semicolon = 59,
        //
        // 摘要:
        //     The equal key.
        Equal = 61,
        //
        // 摘要:
        //     The A key.
        A = 65,
        //
        // 摘要:
        //     The B key.
        B = 66,
        //
        // 摘要:
        //     The C key.
        C = 67,
        //
        // 摘要:
        //     The D key.
        D = 68,
        //
        // 摘要:
        //     The E key.
        E = 69,
        //
        // 摘要:
        //     The F key.
        F = 70,
        //
        // 摘要:
        //     The G key.
        G = 71,
        //
        // 摘要:
        //     The H key.
        H = 72,
        //
        // 摘要:
        //     The I key.
        I = 73,
        //
        // 摘要:
        //     The J key.
        J = 74,
        //
        // 摘要:
        //     The K key.
        K = 75,
        //
        // 摘要:
        //     The L key.
        L = 76,
        //
        // 摘要:
        //     The M key.
        M = 77,
        //
        // 摘要:
        //     The N key.
        N = 78,
        //
        // 摘要:
        //     The O key.
        O = 79,
        //
        // 摘要:
        //     The P key.
        P = 80,
        //
        // 摘要:
        //     The Q key.
        Q = 81,
        //
        // 摘要:
        //     The R key.
        R = 82,
        //
        // 摘要:
        //     The S key.
        S = 83,
        //
        // 摘要:
        //     The T key.
        T = 84,
        //
        // 摘要:
        //     The U key.
        U = 85,
        //
        // 摘要:
        //     The V key.
        V = 86,
        //
        // 摘要:
        //     The W key.
        W = 87,
        //
        // 摘要:
        //     The X key.
        X = 88,
        //
        // 摘要:
        //     The Y key.
        Y = 89,
        //
        // 摘要:
        //     The Z key.
        Z = 90,
        //
        // 摘要:
        //     The left bracket(opening bracket) key.
        LeftBracket = 91,
        //
        // 摘要:
        //     The backslash.
        Backslash = 92,
        //
        // 摘要:
        //     The right bracket(closing bracket) key.
        RightBracket = 93,
        //
        // 摘要:
        //     The grave accent key.
        GraveAccent = 96,
        //
        // 摘要:
        //     The escape key.
        Escape = 0x100,
        //
        // 摘要:
        //     The enter key.
        Enter = 257,
        //
        // 摘要:
        //     The tab key.
        Tab = 258,
        //
        // 摘要:
        //     The backspace key.
        Backspace = 259,
        //
        // 摘要:
        //     The insert key.
        Insert = 260,
        //
        // 摘要:
        //     The delete key.
        Delete = 261,
        //
        // 摘要:
        //     The right arrow key.
        Right = 262,
        //
        // 摘要:
        //     The left arrow key.
        Left = 263,
        //
        // 摘要:
        //     The down arrow key.
        Down = 264,
        //
        // 摘要:
        //     The up arrow key.
        Up = 265,
        //
        // 摘要:
        //     The page up key.
        PageUp = 266,
        //
        // 摘要:
        //     The page down key.
        PageDown = 267,
        //
        // 摘要:
        //     The home key.
        Home = 268,
        //
        // 摘要:
        //     The end key.
        End = 269,
        //
        // 摘要:
        //     The caps lock key.
        CapsLock = 280,
        //
        // 摘要:
        //     The scroll lock key.
        ScrollLock = 281,
        //
        // 摘要:
        //     The num lock key.
        NumLock = 282,
        //
        // 摘要:
        //     The print screen key.
        PrintScreen = 283,
        //
        // 摘要:
        //     The pause key.
        Pause = 284,
        //
        // 摘要:
        //     The F1 key.
        F1 = 290,
        //
        // 摘要:
        //     The F2 key.
        F2 = 291,
        //
        // 摘要:
        //     The F3 key.
        F3 = 292,
        //
        // 摘要:
        //     The F4 key.
        F4 = 293,
        //
        // 摘要:
        //     The F5 key.
        F5 = 294,
        //
        // 摘要:
        //     The F6 key.
        F6 = 295,
        //
        // 摘要:
        //     The F7 key.
        F7 = 296,
        //
        // 摘要:
        //     The F8 key.
        F8 = 297,
        //
        // 摘要:
        //     The F9 key.
        F9 = 298,
        //
        // 摘要:
        //     The F10 key.
        F10 = 299,
        //
        // 摘要:
        //     The F11 key.
        F11 = 300,
        //
        // 摘要:
        //     The F12 key.
        F12 = 301,
        //
        // 摘要:
        //     The F13 key.
        F13 = 302,
        //
        // 摘要:
        //     The F14 key.
        F14 = 303,
        //
        // 摘要:
        //     The F15 key.
        F15 = 304,
        //
        // 摘要:
        //     The F16 key.
        F16 = 305,
        //
        // 摘要:
        //     The F17 key.
        F17 = 306,
        //
        // 摘要:
        //     The F18 key.
        F18 = 307,
        //
        // 摘要:
        //     The F19 key.
        F19 = 308,
        //
        // 摘要:
        //     The F20 key.
        F20 = 309,
        //
        // 摘要:
        //     The F21 key.
        F21 = 310,
        //
        // 摘要:
        //     The F22 key.
        F22 = 311,
        //
        // 摘要:
        //     The F23 key.
        F23 = 312,
        //
        // 摘要:
        //     The F24 key.
        F24 = 313,
        //
        // 摘要:
        //     The F25 key.
        F25 = 314,
        //
        // 摘要:
        //     The 0 key on the key pad.
        KeyPad0 = 320,
        //
        // 摘要:
        //     The 1 key on the key pad.
        KeyPad1 = 321,
        //
        // 摘要:
        //     The 2 key on the key pad.
        KeyPad2 = 322,
        //
        // 摘要:
        //     The 3 key on the key pad.
        KeyPad3 = 323,
        //
        // 摘要:
        //     The 4 key on the key pad.
        KeyPad4 = 324,
        //
        // 摘要:
        //     The 5 key on the key pad.
        KeyPad5 = 325,
        //
        // 摘要:
        //     The 6 key on the key pad.
        KeyPad6 = 326,
        //
        // 摘要:
        //     The 7 key on the key pad.
        KeyPad7 = 327,
        //
        // 摘要:
        //     The 8 key on the key pad.
        KeyPad8 = 328,
        //
        // 摘要:
        //     The 9 key on the key pad.
        KeyPad9 = 329,
        //
        // 摘要:
        //     The decimal key on the key pad.
        KeyPadDecimal = 330,
        //
        // 摘要:
        //     The divide key on the key pad.
        KeyPadDivide = 331,
        //
        // 摘要:
        //     The multiply key on the key pad.
        KeyPadMultiply = 332,
        //
        // 摘要:
        //     The subtract key on the key pad.
        KeyPadSubtract = 333,
        //
        // 摘要:
        //     The add key on the key pad.
        KeyPadAdd = 334,
        //
        // 摘要:
        //     The enter key on the key pad.
        KeyPadEnter = 335,
        //
        // 摘要:
        //     The equal key on the key pad.
        KeyPadEqual = 336,
        //
        // 摘要:
        //     The left shift key.
        LeftShift = 340,
        //
        // 摘要:
        //     The left control key.
        LeftControl = 341,
        //
        // 摘要:
        //     The left alt key.
        LeftAlt = 342,
        //
        // 摘要:
        //     The left super key.
        LeftSuper = 343,
        //
        // 摘要:
        //     The right shift key.
        RightShift = 344,
        //
        // 摘要:
        //     The right control key.
        RightControl = 345,
        //
        // 摘要:
        //     The right alt key.
        RightAlt = 346,
        //
        // 摘要:
        //     The right super key.
        RightSuper = 347,
        //
        // 摘要:
        //     The menu key.
        Menu = 348,
        //
        // 摘要:
        //     The last valid key in this enum.
        LastKey = 348
    }
}